#include "ZiaServerWin.h"
#include	"RequestParser.hpp"
#include	"../Api Headers/DataTree.hpp"
#include	"Request.h"
// Constructor / Destructor
#include		<fstream>
#include	"ManipList.hpp"
#include	<utility>

using namespace std;
extern ManipList<std::pair<std::string, int> >		msgList;

ZiaServerWin::ZiaServerWin()
{
	
}

ZiaServerWin::~ZiaServerWin()
{

}


// Public Methods

void		ZiaServerWin::LaunchServ()
{
	ConfigNListen();
	SelectLoop();
}

// Private Methods

int			ZiaServerWin::ConfigNListen()
{
	struct sockaddr_in	addr;
	WSADATA				wsa;

	WSAStartup(MAKEWORD(2,0), &wsa);
	addr.sin_family = AF_INET;
	addr.sin_port = htons(PORT);
	addr.sin_addr.s_addr = INADDR_ANY;
	_servSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (_servSock < 0)
		return (-1);
	if (bind(_servSock, (struct sockaddr *)&addr, sizeof(addr)) == SOCKET_ERROR)
		return (-2);
	listen(_servSock, SOMAXCONN);
	return (0);
}



int			ZiaServerWin::SelectLoop()
{
	fd_set				StaticRFdSet;
	fd_set				RFdSet;
	int					max = _servSock;
	int					checkSock;
	
	

	FD_ZERO(&StaticRFdSet);
	FD_SET(_servSock, &StaticRFdSet);
	for (;;)
	{
		RFdSet = StaticRFdSet;
		if (select(max + 1, &RFdSet, NULL, NULL, NULL) < 1)
			std::cout << "Select error" << std::endl;
		for(checkSock = 0; checkSock < max + 1; checkSock++)
		{
			if (FD_ISSET(checkSock, &RFdSet)) 
			{
				if (checkSock == _servSock) // Nouveau Client
					max = NewCliSocket(&StaticRFdSet, max);
				else // Traitement du message
					IncomingMsg(checkSock, &StaticRFdSet, &max);
			}
		}
	}
}

int			ZiaServerWin::NewCliSocket(fd_set *StaticRFdSet, int max)
{
	int					lenCliAddr = sizeof(struct sockaddr_in);
	struct sockaddr_in	cliAddr;
	int					cliSock;

	cliSock = accept(_servSock, (struct sockaddr *)&cliAddr, &lenCliAddr);
	FD_SET(cliSock, StaticRFdSet);
	if (max < cliSock)
		max = cliSock;
	return (max);
}

std::string	ZiaServerWin::IncomingMsg(int checkSock, fd_set *StaticRFdSet, int *max)
{
	std::string			msg = "";
	int					it = 0;
	int					reading;
	char				buf[BUFLEN + 1];
	int					max_old;
	std::pair<std::string, int>	*myRequest;

	msg.clear();
	reading = BUFLEN;
	while (reading == BUFLEN)
	{
		reading = recv(checkSock, buf, BUFLEN, NULL);
		buf[reading] = '\0';
		msg.insert(it, buf, reading);
		it += reading;
	}
	myRequest = new std::pair<std::string, int>;
	myRequest->first = msg;
	myRequest->second = checkSock;

	cout << "TEST" << endl;
	msgList.addMessage(myRequest);
	cout << "TESTEND" << endl;
	/* 
	mettre dans une instance message
	envois instance message au parseur
	*/
	FD_CLR(checkSock, StaticRFdSet);
	if (checkSock == *max)
	{
		max_old = *max;
		*max = 0;
		for (checkSock = 0; checkSock < max_old ; checkSock++)
			if ((checkSock > *max) && (FD_ISSET(checkSock, StaticRFdSet)))
				*max = checkSock;
	}
	return (msg);
}

void		ZiaServerWin::CloseConnection()
{
	if (_servSock)
		closesocket(_servSock);
}
